package com.technician.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.technician.common.ResponseResult;
import com.technician.constant.CommonConstant;
import com.technician.exceptionHandler.GlobalSystemException;
import com.technician.mapper.UserMapper;
import com.technician.model.dto.user.UserLoginRequest;
import com.technician.model.dto.user.UserQueryRequest;
import com.technician.model.dto.user.UserRegisterRequest;
import com.technician.model.entity.User;
import com.technician.model.enums.HttpStatusEnum;
import com.technician.model.security.LoginUser;
import com.technician.model.vo.UserVO;
import com.technician.service.UserService;
import com.technician.utils.JwtUtil;
import com.technician.utils.RedisCache;
import com.technician.utils.SqlUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService  {

    // 注入 AuthenticationManager 对象 (去SecurityConfig创建这个Bean)
    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public ResponseResult login(UserLoginRequest userLoginRequest) {
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userLoginRequest.getUserName(), userLoginRequest.getPassword());
        // 需要把 用户的 用户名 和 密码 交给 AuthenticationManager 对象认证
        // 认证会通过一个 UserDetailsService 的接口定义的实现类去查询数据库中的用户账号密码进行认证,所以先要去实现 UserDetailsService 这个接口, 编写我们自己的数据库认证
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        // 判断认证的结果是否为空, 为空认证失败
        if (Objects.isNull(authenticate)) {
            throw new RuntimeException("登陆失败...");
        }
        // 认证通过 , 使用 userId 生成一个 jwt ,  jwt 存入 ResponseResult 进行返回
        // 首先要 编写 JwtUtil 工具类
        // 从认证过后得到的 authenticate 获取 LoginUser(UserDetails)
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        // 获取 userId 作为 subject 生成 JWT
        String userId = loginUser.getUser().getId().toString();
        String jwt = JwtUtil.createJWT(userId);
        // 把 JWT 放进 Map 传给前端
        Map<String, Object> map = new HashMap<>();
        map.put("token", jwt);
        // 把完整的用户信息存入 redis , userId 作为 key
        //首先要连接 redis , application.yml 文件配置 redis , 编写 redis 工具类 ,配置 redis 的配置类(序列化键和值),导入fastjson来序列化
        redisCache.setCacheObject("login:" + userId, loginUser);
        map.put("userInfo", UserVO.objToVo(loginUser.getUser()));
        return new ResponseResult(200, "登录成功...", map);
    }

    @Override
    public ResponseResult register(UserRegisterRequest userRegisterRequest) {
        String userName = userRegisterRequest.getUserName();
        String password = userRegisterRequest.getPassword();
        String checkPassword = userRegisterRequest.getCheckPassword();
        // 判断两次密码是否相同
        if (!password.equals(checkPassword)) {
            // 两次输入的密码不一致
            throw new GlobalSystemException(400,"两次输入的密码不一致");
        }
        //  判断账号是否已经存在(根据姓名查询)
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUserName, userName);
        Integer count = userMapper.selectCount(queryWrapper);
        if (count > 0) {
            // 账号已存在
            throw new GlobalSystemException(400,"账号已存在");
        }
        // 创建账号
        User user = new User();
        BeanUtils.copyProperties(userRegisterRequest, user,"password");
        user.setSex("2");   // 未知性别
        user.setAvatar("https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0");
        user.setPassword(passwordEncoder.encode(password));
        user.setStatus("0");
        user.setUserType("1");
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());

        int insert = userMapper.insert(user);
        if (insert <= 0){
            // 插入失败
            throw new GlobalSystemException(500,"数据库异常");
        }
        return ResponseResult.success(HttpStatusEnum.SUCCESS_RESPONSE);
    }

    /**
     *
     * @param userQueryRequest
     * @return
     */
    @Override
    public QueryWrapper<User> getQueryWrapper(UserQueryRequest userQueryRequest) {
        if (userQueryRequest == null) {
            throw new GlobalSystemException(400,"请求参数异常");
        }
        Long id = userQueryRequest.getId();
        String userName = userQueryRequest.getUserName();
        String userType = userQueryRequest.getUserType();
        String sortField = userQueryRequest.getSortField();
        String sortOrder = userQueryRequest.getSortOrder();
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(id != null, "id", id);
        queryWrapper.eq(StringUtils.isNotBlank(userType), "user_type", userType);
        queryWrapper.like(StringUtils.isNotBlank(userName), "user_name", userName);
        queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC),
                sortField);
        return queryWrapper;
    }
}